home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-9.10-netbook-remix-PL.iso / casper / filesystem.squashfs / usr / lib / python2.6 / zipfile.pyc (.txt) < prev   
Python Compiled Bytecode  |  2009-11-11  |  38KB  |  1,149 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. '''
  5. Read and write ZIP files.
  6. '''
  7. import struct
  8. import os
  9. import time
  10. import sys
  11. import shutil
  12. import binascii
  13. import cStringIO
  14. import stat
  15.  
  16. try:
  17.     import zlib
  18.     crc32 = zlib.crc32
  19. except ImportError:
  20.     zlib = None
  21.     crc32 = binascii.crc32
  22.  
  23. __all__ = [
  24.     'BadZipfile',
  25.     'error',
  26.     'ZIP_STORED',
  27.     'ZIP_DEFLATED',
  28.     'is_zipfile',
  29.     'ZipInfo',
  30.     'ZipFile',
  31.     'PyZipFile',
  32.     'LargeZipFile']
  33.  
  34. class BadZipfile(Exception):
  35.     pass
  36.  
  37.  
  38. class LargeZipFile(Exception):
  39.     '''
  40.     Raised when writing a zipfile, the zipfile requires ZIP64 extensions
  41.     and those extensions are disabled.
  42.     '''
  43.     pass
  44.  
  45. error = BadZipfile
  46. ZIP64_LIMIT = (1 << 31) - 1
  47. ZIP_FILECOUNT_LIMIT = 1 << 16
  48. ZIP_MAX_COMMENT = (1 << 16) - 1
  49. ZIP_STORED = 0
  50. ZIP_DEFLATED = 8
  51. structEndArchive = '<4s4H2LH'
  52. stringEndArchive = 'PK\x05\x06'
  53. sizeEndCentDir = struct.calcsize(structEndArchive)
  54. _ECD_SIGNATURE = 0
  55. _ECD_DISK_NUMBER = 1
  56. _ECD_DISK_START = 2
  57. _ECD_ENTRIES_THIS_DISK = 3
  58. _ECD_ENTRIES_TOTAL = 4
  59. _ECD_SIZE = 5
  60. _ECD_OFFSET = 6
  61. _ECD_COMMENT_SIZE = 7
  62. _ECD_COMMENT = 8
  63. _ECD_LOCATION = 9
  64. structCentralDir = '<4s4B4HL2L5H2L'
  65. stringCentralDir = 'PK\x01\x02'
  66. sizeCentralDir = struct.calcsize(structCentralDir)
  67. _CD_SIGNATURE = 0
  68. _CD_CREATE_VERSION = 1
  69. _CD_CREATE_SYSTEM = 2
  70. _CD_EXTRACT_VERSION = 3
  71. _CD_EXTRACT_SYSTEM = 4
  72. _CD_FLAG_BITS = 5
  73. _CD_COMPRESS_TYPE = 6
  74. _CD_TIME = 7
  75. _CD_DATE = 8
  76. _CD_CRC = 9
  77. _CD_COMPRESSED_SIZE = 10
  78. _CD_UNCOMPRESSED_SIZE = 11
  79. _CD_FILENAME_LENGTH = 12
  80. _CD_EXTRA_FIELD_LENGTH = 13
  81. _CD_COMMENT_LENGTH = 14
  82. _CD_DISK_NUMBER_START = 15
  83. _CD_INTERNAL_FILE_ATTRIBUTES = 16
  84. _CD_EXTERNAL_FILE_ATTRIBUTES = 17
  85. _CD_LOCAL_HEADER_OFFSET = 18
  86. structFileHeader = '<4s2B4HL2L2H'
  87. stringFileHeader = 'PK\x03\x04'
  88. sizeFileHeader = struct.calcsize(structFileHeader)
  89. _FH_SIGNATURE = 0
  90. _FH_EXTRACT_VERSION = 1
  91. _FH_EXTRACT_SYSTEM = 2
  92. _FH_GENERAL_PURPOSE_FLAG_BITS = 3
  93. _FH_COMPRESSION_METHOD = 4
  94. _FH_LAST_MOD_TIME = 5
  95. _FH_LAST_MOD_DATE = 6
  96. _FH_CRC = 7
  97. _FH_COMPRESSED_SIZE = 8
  98. _FH_UNCOMPRESSED_SIZE = 9
  99. _FH_FILENAME_LENGTH = 10
  100. _FH_EXTRA_FIELD_LENGTH = 11
  101. structEndArchive64Locator = '<4sLQL'
  102. stringEndArchive64Locator = 'PK\x06\x07'
  103. sizeEndCentDir64Locator = struct.calcsize(structEndArchive64Locator)
  104. structEndArchive64 = '<4sQ2H2L4Q'
  105. stringEndArchive64 = 'PK\x06\x06'
  106. sizeEndCentDir64 = struct.calcsize(structEndArchive64)
  107. _CD64_SIGNATURE = 0
  108. _CD64_DIRECTORY_RECSIZE = 1
  109. _CD64_CREATE_VERSION = 2
  110. _CD64_EXTRACT_VERSION = 3
  111. _CD64_DISK_NUMBER = 4
  112. _CD64_DISK_NUMBER_START = 5
  113. _CD64_NUMBER_ENTRIES_THIS_DISK = 6
  114. _CD64_NUMBER_ENTRIES_TOTAL = 7
  115. _CD64_DIRECTORY_SIZE = 8
  116. _CD64_OFFSET_START_CENTDIR = 9
  117.  
  118. def is_zipfile(filename):
  119.     '''Quickly see if file is a ZIP file by checking the magic number.'''
  120.     
  121.     try:
  122.         fpin = open(filename, 'rb')
  123.         endrec = _EndRecData(fpin)
  124.         fpin.close()
  125.         if endrec:
  126.             return True
  127.     except IOError:
  128.         pass
  129.  
  130.     return False
  131.  
  132.  
  133. def _EndRecData64(fpin, offset, endrec):
  134.     '''
  135.     Read the ZIP64 end-of-archive records and use that to update endrec
  136.     '''
  137.     fpin.seek(offset - sizeEndCentDir64Locator, 2)
  138.     data = fpin.read(sizeEndCentDir64Locator)
  139.     (sig, diskno, reloff, disks) = struct.unpack(structEndArchive64Locator, data)
  140.     if sig != stringEndArchive64Locator:
  141.         return endrec
  142.     if diskno != 0 or disks != 1:
  143.         raise BadZipfile('zipfiles that span multiple disks are not supported')
  144.     disks != 1
  145.     fpin.seek(offset - sizeEndCentDir64Locator - sizeEndCentDir64, 2)
  146.     data = fpin.read(sizeEndCentDir64)
  147.     (sig, sz, create_version, read_version, disk_num, disk_dir, dircount, dircount2, dirsize, diroffset) = struct.unpack(structEndArchive64, data)
  148.     if sig != stringEndArchive64:
  149.         return endrec
  150.     endrec[_ECD_SIGNATURE] = sig
  151.     endrec[_ECD_DISK_NUMBER] = disk_num
  152.     endrec[_ECD_DISK_START] = disk_dir
  153.     endrec[_ECD_ENTRIES_THIS_DISK] = dircount
  154.     endrec[_ECD_ENTRIES_TOTAL] = dircount2
  155.     endrec[_ECD_SIZE] = dirsize
  156.     endrec[_ECD_OFFSET] = diroffset
  157.     return endrec
  158.  
  159.  
  160. def _EndRecData(fpin):
  161.     '''Return data from the "End of Central Directory" record, or None.
  162.  
  163.     The data is a list of the nine items in the ZIP "End of central dir"
  164.     record followed by a tenth item, the file seek offset of this record.'''
  165.     fpin.seek(0, 2)
  166.     filesize = fpin.tell()
  167.     fpin.seek(-sizeEndCentDir, 2)
  168.     data = fpin.read()
  169.     if data[0:4] == stringEndArchive and data[-2:] == '\x00\x00':
  170.         endrec = struct.unpack(structEndArchive, data)
  171.         endrec = list(endrec)
  172.         endrec.append('')
  173.         endrec.append(filesize - sizeEndCentDir)
  174.         return _EndRecData64(fpin, -sizeEndCentDir, endrec)
  175.     maxCommentStart = max(filesize - 65536 - sizeEndCentDir, 0)
  176.     fpin.seek(maxCommentStart, 0)
  177.     data = fpin.read()
  178.     start = data.rfind(stringEndArchive)
  179.  
  180.  
  181. class ZipInfo(object):
  182.     '''Class with attributes describing each file in the ZIP archive.'''
  183.     __slots__ = ('orig_filename', 'filename', 'date_time', 'compress_type', 'comment', 'extra', 'create_system', 'create_version', 'extract_version', 'reserved', 'flag_bits', 'volume', 'internal_attr', 'external_attr', 'header_offset', 'CRC', 'compress_size', 'file_size', '_raw_time')
  184.     
  185.     def __init__(self, filename = 'NoName', date_time = (1980, 1, 1, 0, 0, 0)):
  186.         self.orig_filename = filename
  187.         null_byte = filename.find(chr(0))
  188.         if null_byte >= 0:
  189.             filename = filename[0:null_byte]
  190.         
  191.         if os.sep != '/' and os.sep in filename:
  192.             filename = filename.replace(os.sep, '/')
  193.         
  194.         self.filename = filename
  195.         self.date_time = date_time
  196.         self.compress_type = ZIP_STORED
  197.         self.comment = ''
  198.         self.extra = ''
  199.         if sys.platform == 'win32':
  200.             self.create_system = 0
  201.         else:
  202.             self.create_system = 3
  203.         self.create_version = 20
  204.         self.extract_version = 20
  205.         self.reserved = 0
  206.         self.flag_bits = 0
  207.         self.volume = 0
  208.         self.internal_attr = 0
  209.         self.external_attr = 0
  210.  
  211.     
  212.     def FileHeader(self):
  213.         '''Return the per-file header as a string.'''
  214.         dt = self.date_time
  215.         dosdate = dt[0] - 1980 << 9 | dt[1] << 5 | dt[2]
  216.         dostime = dt[3] << 11 | dt[4] << 5 | dt[5] // 2
  217.         if self.flag_bits & 8:
  218.             CRC = compress_size = file_size = 0
  219.         else:
  220.             CRC = self.CRC
  221.             compress_size = self.compress_size
  222.             file_size = self.file_size
  223.         extra = self.extra
  224.         if file_size > ZIP64_LIMIT or compress_size > ZIP64_LIMIT:
  225.             fmt = '<HHQQ'
  226.             extra = extra + struct.pack(fmt, 1, struct.calcsize(fmt) - 4, file_size, compress_size)
  227.             file_size = 0xFFFFFFFFL
  228.             compress_size = 0xFFFFFFFFL
  229.             self.extract_version = max(45, self.extract_version)
  230.             self.create_version = max(45, self.extract_version)
  231.         
  232.         (filename, flag_bits) = self._encodeFilenameFlags()
  233.         header = struct.pack(structFileHeader, stringFileHeader, self.extract_version, self.reserved, flag_bits, self.compress_type, dostime, dosdate, CRC, compress_size, file_size, len(filename), len(extra))
  234.         return header + filename + extra
  235.  
  236.     
  237.     def _encodeFilenameFlags(self):
  238.         if isinstance(self.filename, unicode):
  239.             
  240.             try:
  241.                 return (self.filename.encode('ascii'), self.flag_bits)
  242.             except UnicodeEncodeError:
  243.                 return (self.filename.encode('utf-8'), self.flag_bits | 2048)
  244.             
  245.  
  246.         None<EXCEPTION MATCH>UnicodeEncodeError
  247.         return (self.filename, self.flag_bits)
  248.  
  249.     
  250.     def _decodeFilename(self):
  251.         if self.flag_bits & 2048:
  252.             return self.filename.decode('utf-8')
  253.         return self.filename
  254.  
  255.     
  256.     def _decodeExtra(self):
  257.         extra = self.extra
  258.         unpack = struct.unpack
  259.         while extra:
  260.             (tp, ln) = unpack('<HH', extra[:4])
  261.             if tp == 1:
  262.                 if ln >= 24:
  263.                     counts = unpack('<QQQ', extra[4:28])
  264.                 elif ln == 16:
  265.                     counts = unpack('<QQ', extra[4:20])
  266.                 elif ln == 8:
  267.                     counts = unpack('<Q', extra[4:12])
  268.                 elif ln == 0:
  269.                     counts = ()
  270.                 else:
  271.                     raise RuntimeError, 'Corrupt extra field %s' % (ln,)
  272.                 idx = ln >= 24
  273.                 if self.file_size in (0xFFFFFFFFFFFFFFFFL, 0xFFFFFFFFL):
  274.                     self.file_size = counts[idx]
  275.                     idx += 1
  276.                 
  277.                 if self.compress_size == 0xFFFFFFFFL:
  278.                     self.compress_size = counts[idx]
  279.                     idx += 1
  280.                 
  281.                 if self.header_offset == 0xFFFFFFFFL:
  282.                     old = self.header_offset
  283.                     self.header_offset = counts[idx]
  284.                     idx += 1
  285.                 
  286.             
  287.             extra = extra[ln + 4:]
  288.  
  289.  
  290.  
  291. class _ZipDecrypter:
  292.     '''Class to handle decryption of files stored within a ZIP archive.
  293.  
  294.     ZIP supports a password-based form of encryption. Even though known
  295.     plaintext attacks have been found against it, it is still useful
  296.     to be able to get data out of such a file.
  297.  
  298.     Usage:
  299.         zd = _ZipDecrypter(mypwd)
  300.         plain_char = zd(cypher_char)
  301.         plain_text = map(zd, cypher_text)
  302.     '''
  303.     
  304.     def _GenerateCRCTable():
  305.         '''Generate a CRC-32 table.
  306.  
  307.         ZIP encryption uses the CRC32 one-byte primitive for scrambling some
  308.         internal keys. We noticed that a direct implementation is faster than
  309.         relying on binascii.crc32().
  310.         '''
  311.         poly = 0xEDB88320L
  312.         table = [
  313.             0] * 256
  314.         for i in range(256):
  315.             crc = i
  316.             for j in range(8):
  317.                 if crc & 1:
  318.                     crc = crc >> 1 & 2147483647 ^ poly
  319.                     continue
  320.                 crc = crc >> 1 & 2147483647
  321.             
  322.             table[i] = crc
  323.         
  324.         return table
  325.  
  326.     crctable = _GenerateCRCTable()
  327.     
  328.     def _crc32(self, ch, crc):
  329.         '''Compute the CRC32 primitive on one byte.'''
  330.         return crc >> 8 & 16777215 ^ self.crctable[(crc ^ ord(ch)) & 255]
  331.  
  332.     
  333.     def __init__(self, pwd):
  334.         self.key0 = 305419896
  335.         self.key1 = 591751049
  336.         self.key2 = 878082192
  337.         for p in pwd:
  338.             self._UpdateKeys(p)
  339.         
  340.  
  341.     
  342.     def _UpdateKeys(self, c):
  343.         self.key0 = self._crc32(c, self.key0)
  344.         self.key1 = self.key1 + (self.key0 & 255) & 0xFFFFFFFFL
  345.         self.key1 = self.key1 * 134775813 + 1 & 0xFFFFFFFFL
  346.         self.key2 = self._crc32(chr(self.key1 >> 24 & 255), self.key2)
  347.  
  348.     
  349.     def __call__(self, c):
  350.         '''Decrypt a single character.'''
  351.         c = ord(c)
  352.         k = self.key2 | 2
  353.         c = c ^ k * (k ^ 1) >> 8 & 255
  354.         c = chr(c)
  355.         self._UpdateKeys(c)
  356.         return c
  357.  
  358.  
  359.  
  360. class ZipExtFile:
  361.     '''File-like object for reading an archive member.
  362.        Is returned by ZipFile.open().
  363.     '''
  364.     
  365.     def __init__(self, fileobj, zipinfo, decrypt = None):
  366.         self.fileobj = fileobj
  367.         self.decrypter = decrypt
  368.         self.bytes_read = 0x0L
  369.         self.rawbuffer = ''
  370.         self.readbuffer = ''
  371.         self.linebuffer = ''
  372.         self.eof = False
  373.         self.univ_newlines = False
  374.         self.nlSeps = ('\n',)
  375.         self.lastdiscard = ''
  376.         self.compress_type = zipinfo.compress_type
  377.         self.compress_size = zipinfo.compress_size
  378.         self.closed = False
  379.         self.mode = 'r'
  380.         self.name = zipinfo.filename
  381.         self.compreadsize = 65536
  382.         if self.compress_type == ZIP_DEFLATED:
  383.             self.dc = zlib.decompressobj(-15)
  384.         
  385.  
  386.     
  387.     def set_univ_newlines(self, univ_newlines):
  388.         self.univ_newlines = univ_newlines
  389.         self.nlSeps = ('\n',)
  390.         if self.univ_newlines:
  391.             self.nlSeps = ('\r\n', '\r', '\n')
  392.         
  393.  
  394.     
  395.     def __iter__(self):
  396.         return self
  397.  
  398.     
  399.     def next(self):
  400.         nextline = self.readline()
  401.         if not nextline:
  402.             raise StopIteration()
  403.         nextline
  404.         return nextline
  405.  
  406.     
  407.     def close(self):
  408.         self.closed = True
  409.  
  410.     
  411.     def _checkfornewline(self):
  412.         (nl, nllen) = (-1, -1)
  413.         if self.linebuffer:
  414.             if (self.lastdiscard, self.linebuffer[0]) == ('\r', '\n'):
  415.                 self.linebuffer = self.linebuffer[1:]
  416.             
  417.             for sep in self.nlSeps:
  418.                 nl = self.linebuffer.find(sep)
  419.                 if nl >= 0:
  420.                     nllen = len(sep)
  421.                     return (nl, nllen)
  422.             
  423.         
  424.         return (nl, nllen)
  425.  
  426.     
  427.     def readline(self, size = -1):
  428.         '''Read a line with approx. size. If size is negative,
  429.            read a whole line.
  430.         '''
  431.         if size < 0:
  432.             size = sys.maxint
  433.         elif size == 0:
  434.             return ''
  435.         (nl, nllen) = self._checkfornewline()
  436.         buf = self.linebuffer[:nl]
  437.         self.lastdiscard = self.linebuffer[nl:nl + nllen]
  438.         self.linebuffer = self.linebuffer[nl + nllen:]
  439.         return buf + '\n'
  440.  
  441.     
  442.     def readlines(self, sizehint = -1):
  443.         '''Return a list with all (following) lines. The sizehint parameter
  444.         is ignored in this implementation.
  445.         '''
  446.         result = []
  447.         while True:
  448.             line = self.readline()
  449.             if not line:
  450.                 break
  451.             
  452.             result.append(line)
  453.         return result
  454.  
  455.     
  456.     def read(self, size = None):
  457.         if size == 0:
  458.             return ''
  459.         bytesToRead = self.compress_size - self.bytes_read
  460.         if self.decrypter is not None:
  461.             bytesToRead -= 12
  462.         
  463.         if size is not None and size >= 0:
  464.             if self.compress_type == ZIP_STORED:
  465.                 lr = len(self.readbuffer)
  466.                 bytesToRead = min(bytesToRead, size - lr)
  467.             elif self.compress_type == ZIP_DEFLATED:
  468.                 if len(self.readbuffer) > size:
  469.                     bytesToRead = 0
  470.                 else:
  471.                     lr = len(self.rawbuffer)
  472.                     bytesToRead = min(bytesToRead, self.compreadsize - lr)
  473.             
  474.         
  475.         if bytesToRead + self.bytes_read > self.compress_size:
  476.             bytesToRead = self.compress_size - self.bytes_read
  477.         
  478.         if size is None or len(self.readbuffer) <= size:
  479.             bytes = self.readbuffer
  480.             self.readbuffer = ''
  481.         else:
  482.             bytes = self.readbuffer[:size]
  483.             self.readbuffer = self.readbuffer[size:]
  484.         return bytes
  485.  
  486.  
  487.  
  488. class ZipFile:
  489.     ''' Class with methods to open, read, write, close, list zip files.
  490.  
  491.     z = ZipFile(file, mode="r", compression=ZIP_STORED, allowZip64=False)
  492.  
  493.     file: Either the path to the file, or a file-like object.
  494.           If it is a path, the file will be opened and closed by ZipFile.
  495.     mode: The mode can be either read "r", write "w" or append "a".
  496.     compression: ZIP_STORED (no compression) or ZIP_DEFLATED (requires zlib).
  497.     allowZip64: if True ZipFile will create files with ZIP64 extensions when
  498.                 needed, otherwise it will raise an exception when this would
  499.                 be necessary.
  500.  
  501.     '''
  502.     fp = None
  503.     
  504.     def __init__(self, file, mode = 'r', compression = ZIP_STORED, allowZip64 = False):
  505.         '''Open the ZIP file with mode read "r", write "w" or append "a".'''
  506.         if mode not in ('r', 'w', 'a'):
  507.             raise RuntimeError('ZipFile() requires mode "r", "w", or "a"')
  508.         mode not in ('r', 'w', 'a')
  509.         if compression == ZIP_STORED:
  510.             pass
  511.         elif compression == ZIP_DEFLATED:
  512.             if not zlib:
  513.                 raise RuntimeError, 'Compression requires the (missing) zlib module'
  514.             zlib
  515.         else:
  516.             raise RuntimeError, 'That compression method is not supported'
  517.         self._allowZip64 = compression == ZIP_STORED
  518.         self._didModify = False
  519.         self.debug = 0
  520.         self.NameToInfo = { }
  521.         self.filelist = []
  522.         self.compression = compression
  523.         self.mode = key = mode.replace('b', '')[0]
  524.         self.pwd = None
  525.         self.comment = ''
  526.         if isinstance(file, basestring):
  527.             self._filePassed = 0
  528.             self.filename = file
  529.             modeDict = {
  530.                 'r': 'rb',
  531.                 'w': 'wb',
  532.                 'a': 'r+b' }
  533.             
  534.             try:
  535.                 self.fp = open(file, modeDict[mode])
  536.             except IOError:
  537.                 if mode == 'a':
  538.                     mode = key = 'w'
  539.                     self.fp = open(file, modeDict[mode])
  540.                 else:
  541.                     raise 
  542.                 mode == 'a'
  543.             
  544.  
  545.         None<EXCEPTION MATCH>IOError
  546.         self._filePassed = 1
  547.         self.fp = file
  548.         self.filename = getattr(file, 'name', None)
  549.         if key == 'r':
  550.             self._GetContents()
  551.         elif key == 'w':
  552.             pass
  553.         elif key == 'a':
  554.             
  555.             try:
  556.                 self._RealGetContents()
  557.                 self.fp.seek(self.start_dir, 0)
  558.             except BadZipfile:
  559.                 self.fp.seek(0, 2)
  560.             except:
  561.                 None<EXCEPTION MATCH>BadZipfile
  562.             
  563.  
  564.         None<EXCEPTION MATCH>BadZipfile
  565.         if not self._filePassed:
  566.             self.fp.close()
  567.             self.fp = None
  568.         
  569.         raise RuntimeError, 'Mode must be "r", "w" or "a"'
  570.  
  571.     
  572.     def _GetContents(self):
  573.         '''Read the directory, making sure we close the file if the format
  574.         is bad.'''
  575.         
  576.         try:
  577.             self._RealGetContents()
  578.         except BadZipfile:
  579.             if not self._filePassed:
  580.                 self.fp.close()
  581.                 self.fp = None
  582.             
  583.             raise 
  584.  
  585.  
  586.     
  587.     def _RealGetContents(self):
  588.         '''Read in the table of contents for the ZIP file.'''
  589.         fp = self.fp
  590.         endrec = _EndRecData(fp)
  591.         if not endrec:
  592.             raise BadZipfile, 'File is not a zip file'
  593.         endrec
  594.         if self.debug > 1:
  595.             print endrec
  596.         
  597.         size_cd = endrec[_ECD_SIZE]
  598.         offset_cd = endrec[_ECD_OFFSET]
  599.         self.comment = endrec[_ECD_COMMENT]
  600.         concat = endrec[_ECD_LOCATION] - size_cd - offset_cd
  601.         if endrec[_ECD_SIGNATURE] == stringEndArchive64:
  602.             concat -= sizeEndCentDir64 + sizeEndCentDir64Locator
  603.         
  604.         if self.debug > 2:
  605.             inferred = concat + offset_cd
  606.             print 'given, inferred, offset', offset_cd, inferred, concat
  607.         
  608.         self.start_dir = offset_cd + concat
  609.         fp.seek(self.start_dir, 0)
  610.         data = fp.read(size_cd)
  611.         fp = cStringIO.StringIO(data)
  612.         total = 0
  613.         while total < size_cd:
  614.             centdir = fp.read(sizeCentralDir)
  615.             if centdir[0:4] != stringCentralDir:
  616.                 raise BadZipfile, 'Bad magic number for central directory'
  617.             centdir[0:4] != stringCentralDir
  618.             centdir = struct.unpack(structCentralDir, centdir)
  619.             if self.debug > 2:
  620.                 print centdir
  621.             
  622.             filename = fp.read(centdir[_CD_FILENAME_LENGTH])
  623.             x = ZipInfo(filename)
  624.             x.extra = fp.read(centdir[_CD_EXTRA_FIELD_LENGTH])
  625.             x.comment = fp.read(centdir[_CD_COMMENT_LENGTH])
  626.             x.header_offset = centdir[_CD_LOCAL_HEADER_OFFSET]
  627.             (x.create_version, x.create_system, x.extract_version, x.reserved, x.flag_bits, x.compress_type, t, d, x.CRC, x.compress_size, x.file_size) = centdir[1:12]
  628.             (x.volume, x.internal_attr, x.external_attr) = centdir[15:18]
  629.             x._raw_time = t
  630.             x.date_time = ((d >> 9) + 1980, d >> 5 & 15, d & 31, t >> 11, t >> 5 & 63, (t & 31) * 2)
  631.             x._decodeExtra()
  632.             x.header_offset = x.header_offset + concat
  633.             x.filename = x._decodeFilename()
  634.             self.filelist.append(x)
  635.             self.NameToInfo[x.filename] = x
  636.             total = total + sizeCentralDir + centdir[_CD_FILENAME_LENGTH] + centdir[_CD_EXTRA_FIELD_LENGTH] + centdir[_CD_COMMENT_LENGTH]
  637.             if self.debug > 2:
  638.                 print 'total', total
  639.                 continue
  640.  
  641.     
  642.     def namelist(self):
  643.         '''Return a list of file names in the archive.'''
  644.         l = []
  645.         for data in self.filelist:
  646.             l.append(data.filename)
  647.         
  648.         return l
  649.  
  650.     
  651.     def infolist(self):
  652.         '''Return a list of class ZipInfo instances for files in the
  653.         archive.'''
  654.         return self.filelist
  655.  
  656.     
  657.     def printdir(self):
  658.         '''Print a table of contents for the zip file.'''
  659.         print '%-46s %19s %12s' % ('File Name', 'Modified    ', 'Size')
  660.         for zinfo in self.filelist:
  661.             date = '%d-%02d-%02d %02d:%02d:%02d' % zinfo.date_time[:6]
  662.             print '%-46s %s %12d' % (zinfo.filename, date, zinfo.file_size)
  663.         
  664.  
  665.     
  666.     def testzip(self):
  667.         '''Read all the files and check the CRC.'''
  668.         chunk_size = 1048576
  669.         for zinfo in self.filelist:
  670.             
  671.             try:
  672.                 f = self.open(zinfo.filename, 'r')
  673.                 while f.read(chunk_size):
  674.                     pass
  675.             continue
  676.             except BadZipfile:
  677.                 return zinfo.filename
  678.             
  679.  
  680.         
  681.  
  682.     
  683.     def getinfo(self, name):
  684.         """Return the instance of ZipInfo given 'name'."""
  685.         info = self.NameToInfo.get(name)
  686.         if info is None:
  687.             raise KeyError('There is no item named %r in the archive' % name)
  688.         info is None
  689.         return info
  690.  
  691.     
  692.     def setpassword(self, pwd):
  693.         '''Set default password for encrypted files.'''
  694.         self.pwd = pwd
  695.  
  696.     
  697.     def read(self, name, pwd = None):
  698.         '''Return file bytes (as a string) for name.'''
  699.         return self.open(name, 'r', pwd).read()
  700.  
  701.     
  702.     def open(self, name, mode = 'r', pwd = None):
  703.         """Return file-like object for 'name'."""
  704.         if mode not in ('r', 'U', 'rU'):
  705.             raise RuntimeError, 'open() requires mode "r", "U", or "rU"'
  706.         mode not in ('r', 'U', 'rU')
  707.         if not self.fp:
  708.             raise RuntimeError, 'Attempt to read ZIP archive that was already closed'
  709.         self.fp
  710.         if self._filePassed:
  711.             zef_file = self.fp
  712.         else:
  713.             zef_file = open(self.filename, 'rb')
  714.         if isinstance(name, ZipInfo):
  715.             zinfo = name
  716.         else:
  717.             zinfo = self.getinfo(name)
  718.         zef_file.seek(zinfo.header_offset, 0)
  719.         fheader = zef_file.read(sizeFileHeader)
  720.         if fheader[0:4] != stringFileHeader:
  721.             raise BadZipfile, 'Bad magic number for file header'
  722.         fheader[0:4] != stringFileHeader
  723.         fheader = struct.unpack(structFileHeader, fheader)
  724.         fname = zef_file.read(fheader[_FH_FILENAME_LENGTH])
  725.         if fheader[_FH_EXTRA_FIELD_LENGTH]:
  726.             zef_file.read(fheader[_FH_EXTRA_FIELD_LENGTH])
  727.         
  728.         if fname != zinfo.orig_filename:
  729.             raise BadZipfile, 'File name in directory "%s" and header "%s" differ.' % (zinfo.orig_filename, fname)
  730.         fname != zinfo.orig_filename
  731.         is_encrypted = zinfo.flag_bits & 1
  732.         zd = None
  733.         if is_encrypted:
  734.             if not pwd:
  735.                 pwd = self.pwd
  736.             
  737.             if not pwd:
  738.                 raise RuntimeError, 'File %s is encrypted, password required for extraction' % name
  739.             pwd
  740.             zd = _ZipDecrypter(pwd)
  741.             bytes = zef_file.read(12)
  742.             h = map(zd, bytes[0:12])
  743.             if zinfo.flag_bits & 8:
  744.                 check_byte = zinfo._raw_time >> 8 & 255
  745.             else:
  746.                 check_byte = zinfo.CRC >> 24 & 255
  747.             if ord(h[11]) != check_byte:
  748.                 raise RuntimeError('Bad password for file', name)
  749.             ord(h[11]) != check_byte
  750.         
  751.         if zd is None:
  752.             zef = ZipExtFile(zef_file, zinfo)
  753.         else:
  754.             zef = ZipExtFile(zef_file, zinfo, zd)
  755.         if 'U' in mode:
  756.             zef.set_univ_newlines(True)
  757.         
  758.         return zef
  759.  
  760.     
  761.     def extract(self, member, path = None, pwd = None):
  762.         """Extract a member from the archive to the current working directory,
  763.            using its full name. Its file information is extracted as accurately
  764.            as possible. `member' may be a filename or a ZipInfo object. You can
  765.            specify a different directory using `path'.
  766.         """
  767.         if not isinstance(member, ZipInfo):
  768.             member = self.getinfo(member)
  769.         
  770.         if path is None:
  771.             path = os.getcwd()
  772.         
  773.         return self._extract_member(member, path, pwd)
  774.  
  775.     
  776.     def extractall(self, path = None, members = None, pwd = None):
  777.         """Extract all members from the archive to the current working
  778.            directory. `path' specifies a different directory to extract to.
  779.            `members' is optional and must be a subset of the list returned
  780.            by namelist().
  781.         """
  782.         if members is None:
  783.             members = self.namelist()
  784.         
  785.         for zipinfo in members:
  786.             self.extract(zipinfo, path, pwd)
  787.         
  788.  
  789.     
  790.     def _extract_member(self, member, targetpath, pwd):
  791.         """Extract the ZipInfo object 'member' to a physical
  792.            file on the path targetpath.
  793.         """
  794.         if targetpath[-1:] in (os.path.sep, os.path.altsep) and len(os.path.splitdrive(targetpath)[1]) > 1:
  795.             targetpath = targetpath[:-1]
  796.         
  797.         if member.filename[0] == '/':
  798.             targetpath = os.path.join(targetpath, member.filename[1:])
  799.         else:
  800.             targetpath = os.path.join(targetpath, member.filename)
  801.         targetpath = os.path.normpath(targetpath)
  802.         upperdirs = os.path.dirname(targetpath)
  803.         if upperdirs and not os.path.exists(upperdirs):
  804.             os.makedirs(upperdirs)
  805.         
  806.         if member.filename[-1] == '/':
  807.             if not os.path.isdir(targetpath):
  808.                 os.mkdir(targetpath)
  809.             
  810.             return targetpath
  811.         source = self.open(member, pwd = pwd)
  812.         target = file(targetpath, 'wb')
  813.         shutil.copyfileobj(source, target)
  814.         source.close()
  815.         target.close()
  816.         return targetpath
  817.  
  818.     
  819.     def _writecheck(self, zinfo):
  820.         '''Check for errors before writing a file to the archive.'''
  821.         if zinfo.filename in self.NameToInfo:
  822.             if self.debug:
  823.                 print 'Duplicate name:', zinfo.filename
  824.             
  825.         
  826.         if self.mode not in ('w', 'a'):
  827.             raise RuntimeError, 'write() requires mode "w" or "a"'
  828.         self.mode not in ('w', 'a')
  829.         if not self.fp:
  830.             raise RuntimeError, 'Attempt to write ZIP archive that was already closed'
  831.         self.fp
  832.         if zinfo.compress_type == ZIP_DEFLATED and not zlib:
  833.             raise RuntimeError, 'Compression requires the (missing) zlib module'
  834.         not zlib
  835.         if zinfo.compress_type not in (ZIP_STORED, ZIP_DEFLATED):
  836.             raise RuntimeError, 'That compression method is not supported'
  837.         zinfo.compress_type not in (ZIP_STORED, ZIP_DEFLATED)
  838.         if zinfo.file_size > ZIP64_LIMIT:
  839.             if not self._allowZip64:
  840.                 raise LargeZipFile('Filesize would require ZIP64 extensions')
  841.             self._allowZip64
  842.         
  843.         if zinfo.header_offset > ZIP64_LIMIT:
  844.             if not self._allowZip64:
  845.                 raise LargeZipFile('Zipfile size would require ZIP64 extensions')
  846.             self._allowZip64
  847.         
  848.  
  849.     
  850.     def write(self, filename, arcname = None, compress_type = None):
  851.         '''Put the bytes from filename into the archive under the name
  852.         arcname.'''
  853.         if not self.fp:
  854.             raise RuntimeError('Attempt to write to ZIP archive that was already closed')
  855.         self.fp
  856.         st = os.stat(filename)
  857.         isdir = stat.S_ISDIR(st.st_mode)
  858.         mtime = time.localtime(st.st_mtime)
  859.         date_time = mtime[0:6]
  860.         if arcname is None:
  861.             arcname = filename
  862.         
  863.         arcname = os.path.normpath(os.path.splitdrive(arcname)[1])
  864.         while arcname[0] in (os.sep, os.altsep):
  865.             arcname = arcname[1:]
  866.         if isdir:
  867.             arcname += '/'
  868.         
  869.         zinfo = ZipInfo(arcname, date_time)
  870.         zinfo.external_attr = (st[0] & 65535) << 0x10L
  871.         if compress_type is None:
  872.             zinfo.compress_type = self.compression
  873.         else:
  874.             zinfo.compress_type = compress_type
  875.         zinfo.file_size = st.st_size
  876.         zinfo.flag_bits = 0
  877.         zinfo.header_offset = self.fp.tell()
  878.         self._writecheck(zinfo)
  879.         self._didModify = True
  880.         if isdir:
  881.             zinfo.file_size = 0
  882.             zinfo.compress_size = 0
  883.             zinfo.CRC = 0
  884.             self.filelist.append(zinfo)
  885.             self.NameToInfo[zinfo.filename] = zinfo
  886.             self.fp.write(zinfo.FileHeader())
  887.             return None
  888.         fp = open(filename, 'rb')
  889.         self.fp.write(zinfo.FileHeader())
  890.         while None:
  891.             buf = fp.read(8192)
  892.             file_size = file_size + len(buf)
  893.             CRC = crc32(buf, CRC) & 0xFFFFFFFFL
  894.             if cmpr:
  895.                 buf = cmpr.compress(buf)
  896.                 compress_size = compress_size + len(buf)
  897.             
  898.             continue
  899.             fp.close()
  900.             if cmpr:
  901.                 buf = cmpr.flush()
  902.                 compress_size = compress_size + len(buf)
  903.                 self.fp.write(buf)
  904.                 zinfo.compress_size = compress_size
  905.             else:
  906.                 zinfo.compress_size = file_size
  907.         zinfo.CRC = CRC
  908.         zinfo.file_size = file_size
  909.         position = self.fp.tell()
  910.         self.fp.seek(zinfo.header_offset + 14, 0)
  911.         self.fp.write(struct.pack('<LLL', zinfo.CRC, zinfo.compress_size, zinfo.file_size))
  912.         self.fp.seek(position, 0)
  913.         self.filelist.append(zinfo)
  914.         self.NameToInfo[zinfo.filename] = zinfo
  915.  
  916.     
  917.     def writestr(self, zinfo_or_arcname, bytes):
  918.         """Write a file into the archive.  The contents is the string
  919.         'bytes'.  'zinfo_or_arcname' is either a ZipInfo instance or
  920.         the name of the file in the archive."""
  921.         if not isinstance(zinfo_or_arcname, ZipInfo):
  922.             zinfo = ZipInfo(filename = zinfo_or_arcname, date_time = time.localtime(time.time())[:6])
  923.             zinfo.compress_type = self.compression
  924.             zinfo.external_attr = 25165824
  925.         else:
  926.             zinfo = zinfo_or_arcname
  927.         if not self.fp:
  928.             raise RuntimeError('Attempt to write to ZIP archive that was already closed')
  929.         self.fp
  930.         zinfo.file_size = len(bytes)
  931.         zinfo.header_offset = self.fp.tell()
  932.         self._writecheck(zinfo)
  933.         self._didModify = True
  934.         zinfo.CRC = crc32(bytes) & 0xFFFFFFFFL
  935.         if zinfo.compress_type == ZIP_DEFLATED:
  936.             co = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -15)
  937.             bytes = co.compress(bytes) + co.flush()
  938.             zinfo.compress_size = len(bytes)
  939.         else:
  940.             zinfo.compress_size = zinfo.file_size
  941.         zinfo.header_offset = self.fp.tell()
  942.         self.fp.write(zinfo.FileHeader())
  943.         self.fp.write(bytes)
  944.         self.fp.flush()
  945.         if zinfo.flag_bits & 8:
  946.             self.fp.write(struct.pack('<LLL', zinfo.CRC, zinfo.compress_size, zinfo.file_size))
  947.         
  948.         self.filelist.append(zinfo)
  949.         self.NameToInfo[zinfo.filename] = zinfo
  950.  
  951.     
  952.     def __del__(self):
  953.         '''Call the "close()" method in case the user forgot.'''
  954.         self.close()
  955.  
  956.     
  957.     def close(self):
  958.         '''Close the file, and for mode "w" and "a" write the ending
  959.         records.'''
  960.         if self.fp is None:
  961.             return None
  962.         if not self._filePassed:
  963.             self.fp.close()
  964.         
  965.         self.fp = None
  966.  
  967.  
  968.  
  969. class PyZipFile(ZipFile):
  970.     '''Class to create ZIP archives with Python library files and packages.'''
  971.     
  972.     def writepy(self, pathname, basename = ''):
  973.         '''Add all files from "pathname" to the ZIP archive.
  974.  
  975.         If pathname is a package directory, search the directory and
  976.         all package subdirectories recursively for all *.py and enter
  977.         the modules into the archive.  If pathname is a plain
  978.         directory, listdir *.py and enter all modules.  Else, pathname
  979.         must be a Python *.py file and the module will be put into the
  980.         archive.  Added modules are always module.pyo or module.pyc.
  981.         This method will compile the module.py into module.pyc if
  982.         necessary.
  983.         '''
  984.         (dir, name) = os.path.split(pathname)
  985.         if os.path.isdir(pathname):
  986.             initname = os.path.join(pathname, '__init__.py')
  987.             if os.path.isfile(initname):
  988.                 if basename:
  989.                     basename = '%s/%s' % (basename, name)
  990.                 else:
  991.                     basename = name
  992.                 if self.debug:
  993.                     print 'Adding package in', pathname, 'as', basename
  994.                 
  995.                 (fname, arcname) = self._get_codename(initname[0:-3], basename)
  996.                 if self.debug:
  997.                     print 'Adding', arcname
  998.                 
  999.                 self.write(fname, arcname)
  1000.                 dirlist = os.listdir(pathname)
  1001.                 dirlist.remove('__init__.py')
  1002.                 for filename in dirlist:
  1003.                     path = os.path.join(pathname, filename)
  1004.                     (root, ext) = os.path.splitext(filename)
  1005.                     if os.path.isdir(path):
  1006.                         if os.path.isfile(os.path.join(path, '__init__.py')):
  1007.                             self.writepy(path, basename)
  1008.                         
  1009.                     os.path.isfile(os.path.join(path, '__init__.py'))
  1010.                     if ext == '.py':
  1011.                         (fname, arcname) = self._get_codename(path[0:-3], basename)
  1012.                         if self.debug:
  1013.                             print 'Adding', arcname
  1014.                         
  1015.                         self.write(fname, arcname)
  1016.                         continue
  1017.                 
  1018.             elif self.debug:
  1019.                 print 'Adding files from directory', pathname
  1020.             
  1021.             for filename in os.listdir(pathname):
  1022.                 path = os.path.join(pathname, filename)
  1023.                 (root, ext) = os.path.splitext(filename)
  1024.                 if ext == '.py':
  1025.                     (fname, arcname) = self._get_codename(path[0:-3], basename)
  1026.                     if self.debug:
  1027.                         print 'Adding', arcname
  1028.                     
  1029.                     self.write(fname, arcname)
  1030.                     continue
  1031.             
  1032.         elif pathname[-3:] != '.py':
  1033.             raise RuntimeError, 'Files added with writepy() must end with ".py"'
  1034.         
  1035.         (fname, arcname) = self._get_codename(pathname[0:-3], basename)
  1036.         if self.debug:
  1037.             print 'Adding file', arcname
  1038.         
  1039.         self.write(fname, arcname)
  1040.  
  1041.     
  1042.     def _get_codename(self, pathname, basename):
  1043.         '''Return (filename, archivename) for the path.
  1044.  
  1045.         Given a module name path, return the correct file path and
  1046.         archive name, compiling if necessary.  For example, given
  1047.         /python/lib/string, return (/python/lib/string.pyc, string).
  1048.         '''
  1049.         file_py = pathname + '.py'
  1050.         file_pyc = pathname + '.pyc'
  1051.         file_pyo = pathname + '.pyo'
  1052.         if os.path.isfile(file_pyo) and os.stat(file_pyo).st_mtime >= os.stat(file_py).st_mtime:
  1053.             fname = file_pyo
  1054.         elif not os.path.isfile(file_pyc) or os.stat(file_pyc).st_mtime < os.stat(file_py).st_mtime:
  1055.             import py_compile as py_compile
  1056.             if self.debug:
  1057.                 print 'Compiling', file_py
  1058.             
  1059.             
  1060.             try:
  1061.                 py_compile.compile(file_py, file_pyc, None, True)
  1062.             except py_compile.PyCompileError:
  1063.                 err = None
  1064.                 print err.msg
  1065.  
  1066.             fname = file_pyc
  1067.         else:
  1068.             fname = file_pyc
  1069.         archivename = os.path.split(fname)[1]
  1070.         if basename:
  1071.             archivename = '%s/%s' % (basename, archivename)
  1072.         
  1073.         return (fname, archivename)
  1074.  
  1075.  
  1076.  
  1077. def main(args = None):
  1078.     import textwrap as textwrap
  1079.     USAGE = textwrap.dedent('        Usage:\n            zipfile.py -l zipfile.zip        # Show listing of a zipfile\n            zipfile.py -t zipfile.zip        # Test if a zipfile is valid\n            zipfile.py -e zipfile.zip target # Extract zipfile into target dir\n            zipfile.py -c zipfile.zip src ... # Create zipfile from sources\n        ')
  1080.     if args is None:
  1081.         args = sys.argv[1:]
  1082.     
  1083.     if not args or args[0] not in ('-l', '-c', '-e', '-t'):
  1084.         print USAGE
  1085.         sys.exit(1)
  1086.     
  1087.     if args[0] == '-l':
  1088.         if len(args) != 2:
  1089.             print USAGE
  1090.             sys.exit(1)
  1091.         
  1092.         zf = ZipFile(args[1], 'r')
  1093.         zf.printdir()
  1094.         zf.close()
  1095.     elif args[0] == '-t':
  1096.         if len(args) != 2:
  1097.             print USAGE
  1098.             sys.exit(1)
  1099.         
  1100.         zf = ZipFile(args[1], 'r')
  1101.         zf.testzip()
  1102.         print 'Done testing'
  1103.     elif args[0] == '-e':
  1104.         if len(args) != 3:
  1105.             print USAGE
  1106.             sys.exit(1)
  1107.         
  1108.         zf = ZipFile(args[1], 'r')
  1109.         out = args[2]
  1110.         for path in zf.namelist():
  1111.             if path.startswith('./'):
  1112.                 tgt = os.path.join(out, path[2:])
  1113.             else:
  1114.                 tgt = os.path.join(out, path)
  1115.             tgtdir = os.path.dirname(tgt)
  1116.             if not os.path.exists(tgtdir):
  1117.                 os.makedirs(tgtdir)
  1118.             
  1119.             fp = open(tgt, 'wb')
  1120.             fp.write(zf.read(path))
  1121.             fp.close()
  1122.         
  1123.         zf.close()
  1124.     elif args[0] == '-c':
  1125.         if len(args) < 3:
  1126.             print USAGE
  1127.             sys.exit(1)
  1128.         
  1129.         
  1130.         def addToZip(zf, path, zippath):
  1131.             if os.path.isfile(path):
  1132.                 zf.write(path, zippath, ZIP_DEFLATED)
  1133.             elif os.path.isdir(path):
  1134.                 for nm in os.listdir(path):
  1135.                     addToZip(zf, os.path.join(path, nm), os.path.join(zippath, nm))
  1136.                 
  1137.             
  1138.  
  1139.         zf = ZipFile(args[1], 'w', allowZip64 = True)
  1140.         for src in args[2:]:
  1141.             addToZip(zf, src, os.path.basename(src))
  1142.         
  1143.         zf.close()
  1144.     
  1145.  
  1146. if __name__ == '__main__':
  1147.     main()
  1148.  
  1149.